﻿using System.Globalization;
using GamFi.Admin.API.Application.Contracts.Purchase.GetPurchases;
using GamFi.Admin.API.Application.Exceptions;
using GamFi.Admin.API.Application.Interfaces;
using GamFi.Admin.API.Application.Resources;
using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Localization;

namespace GamFi.Admin.API.Application.Features.Queries.Purchase.GetPurchases;

/// <summary>
/// Обработчик запроса для получения списка покупок.
/// </summary>
public class GetPurchasesQueryHandler : IRequestHandler<GetPurchasesQuery, GetPurchasesResponse>
{
    private readonly IDbContext _dbContext;
    private readonly IStringLocalizer<ExceptionMessages> _localizer;

    /// <summary>
    /// Конструктор обработчика запроса для получения списка покупок.
    /// </summary>
    /// <param name="dbContext">Контекст базы данных.</param>
    /// <param name="localizer"></param>
    public GetPurchasesQueryHandler(IDbContext dbContext, IStringLocalizer<ExceptionMessages> localizer)
    {
        _dbContext = dbContext;
        _localizer = localizer;
    }

    /// <summary>
    /// Обработка запроса для получения списка покупок.
    /// </summary>
    /// <param name="request">Запрос на получение списка покупок.</param>
    /// <param name="cancellationToken">Токен для отмены операции.</param>
    /// <returns>Ответ с списком покупок.</returns>
    public async Task<GetPurchasesResponse> Handle(GetPurchasesQuery request, CancellationToken cancellationToken)
    {
        if (request is null)
            throw new RequestException(_localizer[nameof(RequestException.RequestIsEmpty)]);

        // Получаем запрос на основе всех покупок
        IQueryable<Domain.Entities.Purchase> query = _dbContext.Purchases;

        // Применяем фильтр, если он предоставлен
        if (!string.IsNullOrEmpty(request.Filter))
        {
            query = query.Where(purchase => 
                purchase.WalletId.ToString().Contains(request.Filter) || 
                purchase.TokenId.ToString().Contains(request.Filter) ||
                purchase.Amount.ToString(CultureInfo.CurrentCulture).Contains(request.Filter) ||
                purchase.Id.ToString().Contains(request.Filter));
        }

        // Применяем пагинацию
        var purchases = await query
            .Skip(request.PageNumber * request.PageSize)
            .Take(request.PageSize)
            .ToListAsync(cancellationToken);
        
        // Маппинг покупок в GetPurchasesResponse
        var response = new GetPurchasesResponse
        {
            Purchases = purchases.Select(purchase => new PurchaseDto
            {
                PurchaseId = purchase.Id,
                Amount = purchase.Amount,
                Date = purchase.Date,
                WalletId = purchase.WalletId,
                TokenId = purchase.TokenId
            }).ToList()
        };

        return response;
    }
}